Use case: Dual channel DAC transfer using DMA

This use case demonstrates how to transfer samples to two DAC channels using DMA.

Sequence diagram

Dual channel DAC transfer using DMA

@startuml
participant "Application" as App
participant "DAC" as DAC
participant "DMA driver" as dma
participant "DMA IRQ handler" as isr

App -> DAC: HAL_DAC_ConfigChannel()
App -> DAC: HAL_DAC_ConfigChannel()
App -> DAC: HAL_DACEx_DualSetValue()
App -> DAC: HAL_DACEx_DualStart_DMA()

DAC -> dma : HAL_DMA_Start_IT()
isr -> dma : IRQ_HANDLER()
dma -> DAC : DAC_DMAConvCpltCh1()
DAC -> App : APP callback over: weak HAL_DAC_ConvCpltCallbackCh1() / HAL_DACEx_ConvCpltCallbackCh2()

App -> DAC: HAL_DACEx_DualStop_DMA()
DAC -> dma: HAL_DMA_Abort()
@enduml

Code snippet

HAL1

HAL2

uint32_t aEscalator12bit[6] = {0x0, 0x330, 0x660, 0x990, 0xCC0, 0xFF0};
DAC_ChannelConfTypeDef sConfig;

sConfig.DAC_HighFrequency = DAC_HIGH_FREQUENCY_INTERFACE_MODE_ABOVE_80MH;
sConfig.DAC_DMADoubleDataMode = DISABLE;
sConfig.DAC_SignedFormat = DISABLE;
sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
sConfig.DAC_Trigger = DAC_TRIGGER_T1_TRGO;
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_EXTERNAL;
sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
sConfig.DAC_TrimmingValue = 31;
HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1);
HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_2);

HAL_DACEx_DualSetValue(&hdac1, DAC_ALIGN_12B_R, 0x0FFF, 0x07FF);

HAL_DACEx_DualStart_DMA(&hdac1, DAC_CHANNEL_1, aEscalator12bit, 6, DAC_ALIGN_12B_R);

HAL_DACEx_DualStop_DMA(&hdac1, DAC_CHANNEL_1);
uint32_t aEscalator12bit[6] = {0x0, 0x330, 0x660, 0x990, 0xCC0, 0xFF0};
hal_dac_dual_channel_config_t dacDualChannelConfig;

hal_dac_config_t p_config;
p_config.high_frequency_mode = HAL_DAC_HIGH_FREQ_MODE_ABOVE_80MHZ;
HAL_DAC_SetConfig(&hdac, &p_config);
dacDualChannelConfig.channel1_config_t.data_sign_format  = HAL_DAC_SIGN_FORMAT_UNSIGNED;
dacDualChannelConfig.channel1_config_t.trigger           = HAL_DAC_TRIGGER_TIM1_TRGO;
dacDualChannelConfig.channel1_config_t.output_buffer     = HAL_DAC_OUTPUT_BUFFER_ENABLED;
dacDualChannelConfig.channel1_config_t.output_connection = HAL_DAC_OUTPUT_CONNECTION_EXTERNAL;

/* Config Channel 2 */
dacDualChannelConfig.channel2_config_t.data_sign_format  = HAL_DAC_SIGN_FORMAT_UNSIGNED;
dacDualChannelConfig.channel2_config_t.trigger           = HAL_DAC_TRIGGER_TIM1_TRGO;
dacDualChannelConfig.channel2_config_t.output_buffer     = HAL_DAC_OUTPUT_BUFFER_ENABLED;
dacDualChannelConfig.channel2_config_t.output_connection = HAL_DAC_OUTPUT_CONNECTION_EXTERNAL;

dacDualChannelConfig.alignment = HAL_DAC_DATA_ALIGN_12_BITS_RIGHT;

HAL_DAC_SetConfigDualChannel(&hdac, &dacDualChannelConfig);
HAL_DAC_SetDualChannelData(&hdac, 0x0FFF);

HAL_DAC_StartDualChannel_DMA(&hdac, aEscalator12bit, 6);

HAL_DAC_StopDualChannel_DMA(&hdac);

Key changes

  1. In HAL2, dual-channel configuration uses a dedicated configuration structure and API (HAL_DAC_SetConfigDualChannel()).

  2. In HAL2, the DMA transfer is started/stopped with dual-channel specific APIs (HAL_DAC_StartDualChannel_DMA() and HAL_DAC_StopDualChannel_DMA()).